using System;
using needle.Services.astra.Collections;
using System.IO;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using System.Collections.Generic;

namespace needle.Services.astra.Db4o
{
	/// <summary>
	/// List of documents open/saved from/to db4o database files.
	/// </summary>
	public class Db4oDocuments : FileDocuments
	{
		/// <summary>
		/// See <see cref="FileDocuments.Open(string, bool)"/>.
		/// Calls <see cref="OpenDatabase"/>, gets <see cref="IDocument"/> from it, fully activates the document and closes the database.
		/// </summary>
		/// <param name="filePath">File path.</param>
		/// <param name="readOnly">Whether to use read only mode.</param>
		/// <returns>Document if found, otherwise null.</returns>
		protected override IDocument Open(string filePath, bool readOnly)
		{
			IObjectContainer db = OpenDatabase(filePath, readOnly);
			IDocument document = null;
			IList<IDocument> documents = db.Query<IDocument>();
			if (documents.Count > 0)
			{
				document = documents[0];
				db.Activate(document, int.MaxValue);
			}
			db.Close();
			return document;
		}
		/// <summary>
		/// See <see cref="FileDocuments.Save(IDocument, string)"/>.
		/// Calls <see cref="OpenDatabase"/>, sets <see cref="IDocument"/> to it and closes it.
		/// </summary>
		/// <param name="document">Document.</param>
		/// <param name="filePath">File path.</param>
		protected override void Save(IDocument document, string filePath)
		{
			IObjectContainer db = OpenDatabase(filePath, false);
			db.Set(document);
			db.Close();
		}

		/// <summary>
		/// Opens db4o database at <paramref name="filePath"/>.
		/// </summary>
		/// <remarks>
		/// db4o database is configured to use <see cref="NonSerializedAttribute"/> as <see cref="TransientAttribute"/>.
		/// </remarks>
		/// <param name="filePath">File path.</param>
		/// <param name="readOnly">
		/// Whether to use read only mode - set to <see cref="IConfiguration.ReadOnly"/>.
		/// </param>
		/// <returns>Database.</returns>
		protected virtual IObjectContainer OpenDatabase(string filePath, bool readOnly)
		{
			IConfiguration config = Db4oFactory.Configure();
			config.MarkTransient(typeof(NonSerializedAttribute).FullName);
			config.ReadOnly(readOnly);
			return Db4oFactory.OpenFile(config, filePath);
		}
	}
}
